package com.sunni.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sunni.entity.User;
import com.sunni.entity.VO;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Controller
@RequestMapping("/user")
public class UserController {

// !!!!!!!!!!!!!!!!!!!!!!!!!!springmvc的数据响应!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

/*-------------------返 视图-----------------------*/
    /**
     * 02.返回页面 (以字符串方法)
     * @return 页面 (字符串方式)
     */
    @RequestMapping("/save02")
    public String save02(){
        System.out.println("Controller save running...");
        return "success"; //视图解析器
//        return "redirect:/view/success.jsp"; // 重定向不能访问WEB-INF, 因为重定向第二次是直接访问 相当于直接访问WEB-INF, 会报404。
//        return "forward:/WEB-INF/view/success.jsp";
    }

    /**
     * 03. 返回ModelAndView
     * @return 数据+视图
     */
    @RequestMapping("save03")
    public ModelAndView save03(){
        ModelAndView modelAndView = new ModelAndView();
        // 放视图
        modelAndView.setViewName("index");
        // 放数据
        modelAndView.addObject("username","Sunni");
        return modelAndView;
    }

    /**
     * 04-1. springmvc, 为你自动注入ModelAndView
     * @param modelAndView
     * @return
     */
    @RequestMapping("save04_1")
    public ModelAndView save04_1(ModelAndView modelAndView){
        modelAndView.addObject("username","Sunni");
        modelAndView.setViewName("index");
        return modelAndView;
    }
    // 04-2. springmvc自动注入数据，视图自己写。
    @RequestMapping("save04_2")
    public String save04_2(Model model){
        model.addAttribute("username","Sunni");
        return "index";
    }

    /**
     * 05. 自动获取request对象
     * @param request 是Tomcat给的，不是springmvc给的
     * @return index视图
     */
    @RequestMapping("/save05")
    public String save05(HttpServletRequest request){ //request是Tomcat给的，不是springmvc的。
        request.setAttribute("username","Sunni, From Request!");
        return "index";
    }

/*--------------------返 数据-------------------------*/

    /**
     * 06-1. 页面打印数据
     * @param response 问Tomcat要Response，进行打印
     * @throws IOException
     */
    @RequestMapping("/save06_1")
    public void save06_1(HttpServletResponse response) throws IOException {
        response.getWriter().print("Hello Sunni !");
    }

    // 06-2. 告诉springmvc 这是返回数据，不是返回视图进行跳转，springmvc直接给你打印。
    @RequestMapping("/save06_2")
    @ResponseBody
    public String save06_2(){
        return "Hello Sunni, From @ResponseBody !";
    }

    /**
     * 07. 返回json数据 (使用jackson工具，把对象转成json串)
     * @param objectMapper springmvc给你一个jackson对象
     * @return
     * @throws JsonProcessingException
     */
    @RequestMapping("/save07")
    @ResponseBody
    public String save07(ObjectMapper objectMapper) throws JsonProcessingException {
        User user = new User(22, "Sunni");
        //jackson对象的writeValueAsString的工具: 把对象转成串。
        String userJson = objectMapper.writeValueAsString(user);
        return userJson;
    }

    /**
     * 08. 返回json对象，用springmvc的处理映射器，不再需要jackson了。
     * @return json对象
     */
    @RequestMapping("/save08")
    @ResponseBody
    public User save08(){
        User user = new User(22, "Sunni By 处理映射器");
        return user;
    }

    /**
     * 09. 返回json对象，优化springmvc的处理映射器，使用注解标签自动配置处理映射器。
     * 在springmvc.xml把刚刚处理映射器的配置注了，加注解标签。
     * @return json对象
     */
    @RequestMapping("/save09")
    @ResponseBody
    public User save09(){
        User user = new User(22, "Sunni By 处理映射器优化版本");
        return user;
    }


// !!!!!!!!!!!!!!!!!!!!!!!!!!springmvc的接收请求!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    /**
     * 12. 接收 普通类型
     * 接收url请求, 接收2个参数。url发来的全是string类型， 如有int类型 springmvc做自动类型转化(string->int)。
     * @param name https://localhost/user/save11?name=Sunni&age=22
     * @param age https://localhost/user/save11?name=Sunni&age=22
     */
    @RequestMapping("/save12")
    @ResponseBody //即使什么也不返回也加@ResponseBody, 代表不返回页面,返回void数据 什么数据也不返回。
    public void save12(String name, int age){
        System.out.println("name = " + name);
        System.out.println("age = " + age);
    }

    /**
     * 13. 接收java类
     * 接收url请求里的参数名字 和 准备封装的java类的属性名一致，springmvc则自动把这些参数封装成一个java类。
     * @param user url参数被springmvc自动封装成java类。
     */
    @RequestMapping("/save13")
    @ResponseBody
    public void save13(User user){
        System.out.println("user = " + user);
    }

    /**
     * 14 .接收数组
     * url请求里 有多个相同名字的参数 和 controller形参定义的数组名字相同，则把这一堆参数和这个数组做映射。
     * @param user url多个都叫user的参数 : http://localhost/user/save14?user=Sunni&user=Amiee&user=Amanda
     *             user[] = {Sunni,Amiee,Amanda}
     */
    @RequestMapping("/save14")
    @ResponseBody
    public void save14(String[] user){
        System.out.println("user[] = " + Arrays.toString(user));
    }

    /**
     * 15 . 接收集合
     * @param vo 借助第三个类VO, VO:List<User> userList, 1.把一堆user对象提交到VO类 封装user集合 (现在VO里就有一个List<User>集合了)。2.springmvc自动把这些对象看成VO的属性userList, 接收VO。3. 从VO取出userList 打印展示。
     */
    @RequestMapping("/save15")
    @ResponseBody
    public void save15(VO vo){
        System.out.println(vo);
    }

    /**
     * 16. 接收ajax
     * @param userList 前台以ajax请求 发来的json格式的userList集合
     *
     *  浏览器报找不到jq文件，涉及静态资源访问权限问题    --springmvc.xml <mvc:resources mapping="/js/**" location="/js/"/>
     */
    @RequestMapping("/save16")
    @ResponseBody
    public void save16(@RequestBody List<User> userList){
        System.out.println("userList = " + userList);
    }

    /**
     * 19. 数据绑定@RequestParam, 前台url参数名字和后台controller方法的形参名字 不一样，把两个名字不一样的参数匹配关联起来。
     * @param name  前台叫username, 后台叫name。匹配关联它们。
     */
    @RequestMapping("/save19")
    @ResponseBody
    public void save19(@RequestParam(value = "username",required = true,defaultValue = "Sunni")String name){
        System.out.println("name = " + name);
    }

    /**
     * 20. Restful风格url  /user/save20/lisi  {占位参数名}必须和@PathVariable(value = "解析参数名")相同
     * @param name
     */
    @RequestMapping("/save20/{username}") //最后那个参数名字叫username,占位
    @ResponseBody
    public void save20(@PathVariable(value = "username") String name){ //@PathVariable ：1. 解析占位 要求你必须有一个和value一样的占位参数名 , 2. 关系匹配 ，把那个占位的数取出来 放进controller方法的匹配的形参里。
        System.out.println("name = " + name);
    }


    /** 21. 自定义转化器 你输入2020-01-01的格式, java也能识别为日期类
     *
     * @param date 前台2020-01-01, java能识别2020/01/01, 格式不匹配,报400 Bad Request  .
     */
    @RequestMapping("/save21")
    @ResponseBody
    public void save21(Date date){
        System.out.println("date = " + date);
    }

    /**
     * 22. 获得Servlet常用的API：Request、Response、Session
     * @param request tomcat给的
     * @param response tomcat给的
     * @param session tomcat给的
     */
    @RequestMapping("/save22")
    @ResponseBody
    public void save22(HttpServletRequest request, HttpServletResponse response, HttpSession session){
        System.out.println("request = " + request);
        System.out.println("response = " + response);
        System.out.println("session = " + session);
    }

    /**
     * 23-1 . 获取浏览器-开发者工具-Network(抓包)-Name(点一个请求)-Headers-Request Headers(请求头的一个参数)
     * @param name
     */
    @RequestMapping("/save23_1")
    @ResponseBody
    public void save23_1(@RequestHeader(value = "Cookie") String name){
        System.out.println("name = " + name);
    }

    /**
     * 23-2. 单独获取cookie值 ，Request Headers-Cookie, cookie比较常用 单独定义了一个获取它的标签。
     * @param name
     */
    @RequestMapping("/save23_2")
    @ResponseBody
    public void save23_2(@CookieValue(value = "JSESSIONID") String name){
        System.out.println("name = " + name);
    }

    /**
     * 25、26单文件上传
     * @param name 输入的文件名
     * @param uploadFile 上传的文件
     */
    @RequestMapping("/save25")
    @ResponseBody
    public void save25(String name, MultipartFile uploadFile) throws IOException { //两个参数, 必须和fileupload.jsp的form表单的input框的name相同。因为springmvc根据名字做自动映射
        /*day04-26 上传的文件存放到磁盘*/
        // 1. 获得上传文件的名称
        String originalFilename = uploadFile.getOriginalFilename();
        // 2. 存到本地磁盘
        uploadFile.transferTo(new File("F:\\uploadtest\\"+originalFilename)); //指定的存放位置(文件夹)必须已经创建好了，否则500---FileNotFoundException
    }

    /**
     * 多文件上传，用数组接，然后遍历数组取出每一个文件，存到本地。
     * @param name
     * @param uploadFile
     * @throws IOException
     */
    @RequestMapping("/save27")
    @ResponseBody
    public void save27(String name, MultipartFile[] uploadFile) throws IOException {
        for (MultipartFile multipartFile : uploadFile) {
            // 1. 获取文件名
            String originalFilename = multipartFile.getOriginalFilename();
            // 2. 存到本地磁盘
            multipartFile.transferTo(new File("F:\\uploadtest\\"+originalFilename));
        }
    }


}
